home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / windownt / queue.zip / QUEUE / QUEUE.C < prev    next >
C/C++ Source or Header  |  1992-10-11  |  16KB  |  668 lines

  1. /************************************************************************\
  2. * The enclosed files, "the software," is provided by 
  3. * Microsoft Corporation "as is" without warranty of any kind. 
  4. * MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, 
  5. * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY 
  6. * AND FITNESS FOR A PARTICULAR PURPOSE.  You assume all risks of 
  7. * using the software.
  8. * The software is Copyright (c) 1992 Microsoft Corporation.
  9. * Original Author: John M. Hall, Microsoft SDE  9/1/92
  10. *
  11. * You are granted the right to freely distribute this software.
  12. * You are granted the right to make changes provided this comment block
  13. * is retained without modification and you acknowledge the changes.
  14. \************************************************************************/
  15. /************************************************************************\
  16. *
  17. *  MODULE:      QUEUE.C
  18. *
  19. *  PURPOSE:     Simple shared memory management.
  20. *
  21. *  FUNCTIONS:   QueueEntry() - DLL entry point
  22. *
  23. *
  24. *
  25. *  COMMENTS:    
  26. *
  27. ************************************************************************/
  28. #define QUEUE_DLL_C
  29.  
  30. #include <stdio.h>
  31. #include <memory.h>
  32. #include <windows.h>
  33. #include <winbase.h>
  34. #include <string.h>
  35. #include <malloc.h>
  36.  
  37. #define DEBUG
  38. #define DOSWIN32
  39. #include "Queue.h"
  40.  
  41. /************************************************************************\
  42. *
  43. *  FUNCTION:    QueueEntry
  44. *
  45. *  INPUTS:      hDLL       - handle of DLL
  46. *               dwReason   - indicates why DLL called
  47. *               lpReserved - reserved
  48. *
  49. *  RETURNS:     TRUE for success, FALSE on error
  50. *
  51. *               Note that the retuRn value is used only when
  52. *               dwReason = DLL_PROCESS_ATTACH.
  53. *
  54. *  GLOBAL VARS: See Queue.h for list of global variables.
  55. *
  56. *  COMMENTS:    Modified from simple dll sample
  57. *
  58. \************************************************************************/
  59. void queue_cleanup()
  60. {
  61.     return;
  62. }
  63.  
  64. BOOL  QueueEntry (HANDLE hDLL, DWORD dwReason, LPVOID lpReserved)
  65.   switch (dwReason)
  66.   { 
  67.   case DLL_PROCESS_ATTACH:
  68.       { 
  69.       /******************************************************************\
  70.       *  DLL is attaching to the address space of the current process.
  71.       \******************************************************************/
  72.       BOOL bFlag;
  73.  
  74.       fp_log = fopen( "hp_shr.log", "a+");
  75.  
  76.       //
  77.       // Attach control memory for Queues
  78.       //
  79.       bFlag = attach_ctl();
  80.  
  81.       if (!bFlag)
  82.           fclose(fp_log);
  83.  
  84.       AssertBox( bFlag, "Attach Memory");
  85.  
  86.       return(bFlag);
  87.       break;
  88.     }
  89.  
  90.     case DLL_THREAD_ATTACH:
  91.  
  92.       /******************************************************************\
  93.       *  A new thread is being created in the current process.
  94.       \******************************************************************/
  95.  
  96.       break;
  97.     case DLL_THREAD_DETACH:
  98.  
  99.       /******************************************************************\
  100.       *  A thread is exiting cleanly.
  101.       \******************************************************************/
  102.  
  103.       break;
  104.     case DLL_PROCESS_DETACH:
  105.  
  106.       /******************************************************************\
  107.       *  The calling process is detaching the DLL from its address space.
  108.       \******************************************************************/
  109.  
  110.       queue_cleanup();
  111.       fclose(fp_log);
  112.       UnmapViewOfFile(lpCtrlBase);
  113.       CloseHandle(hControl);
  114.       break;
  115.   }
  116.   return TRUE;
  117.   UNREFERENCED_PARAMETER(hDLL);
  118.   UNREFERENCED_PARAMETER(lpReserved);
  119. }
  120.  
  121. VOID MyAssertBox( const char *title, const char *exp,
  122.         const char *file, int line)
  123.         {
  124.         char buffer[512];
  125.  
  126.         sprintf( buffer, "Assert(%s) at (%s::%d)", exp, file, line);
  127.         MessageBox (NULL, title, buffer, MB_OK | MB_ICONHAND);
  128.         }
  129.  
  130. BOOL attach_ctl()
  131.     {
  132.     PQUEUE_DATA  pqd;
  133.     int ii;
  134.  
  135.  
  136.     SetErrorMode(SEM_FAILCRITICALERRORS);
  137.  
  138.     hGlobalSem = CreateSemaphore( NULL, 0, 1, "JMH_QUEUE_SEM");
  139.  
  140.     if (hGlobalSem)
  141.         {
  142.         //
  143.         // This is correct, we use GetLastError() to find out how the
  144.         // function succeeded!
  145.         //
  146.         if (GetLastError() == ERROR_ALREADY_EXISTS)
  147.             {
  148.             //
  149.             // We didn't create it, just attach to it so we need to
  150.             // wait till its free.
  151.             //
  152.             WaitForSingleObject(hGlobalSem, INFINITE);
  153.             dwProcesses++;
  154.             }
  155.         else
  156.             {
  157.             dwProcesses = 1;
  158.             }
  159.  
  160.         //
  161.         // The heart of the matter, create the memory mapped files.
  162.         //
  163.         hControl = CreateFileMapping(
  164.             (HANDLE) INFINITE,
  165.             NULL,
  166.             PAGE_READWRITE,
  167.             0,
  168.             64 * 1024,
  169.             "JMH_QUEUE_CTRL");
  170.  
  171.         if (hControl == NULL)
  172.             fprintf( fp_log,  "CreateFileMapping Failed\n");
  173.  
  174.         //
  175.         // Now attach the memory to the correct addresses
  176.         //
  177.         lpCtrlBase = MapViewOfFile( hControl, FILE_MAP_WRITE, 0, 0, 0);
  178.  
  179.         if (lpCtrlBase == NULL)
  180.             {
  181.             fprintf( fp_log,  "MapViewOfFile Failed\n");
  182.             ReleaseSemaphore(hGlobalSem, 1, NULL);
  183.             CloseHandle(hControl);
  184.             return(FALSE);
  185.             }
  186.  
  187.         //
  188.         // First time initialization.
  189.         //
  190.         if (dwProcesses == 1)
  191.             {
  192.             iQueues = 0;
  193.             pqd = (PQUEUE_DATA) lpCtrlBase;
  194.  
  195.             for (ii = 0; ii < MAX_QUEUES; ii++ )
  196.                 {
  197.                 pqd[ii].aQueueName = 0;
  198.                 pqd[ii].sElements  = 0;
  199.                 }
  200.             }
  201.  
  202.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  203.  
  204.         return(TRUE);
  205.  
  206.         }
  207.     else
  208.         return (FALSE);
  209.     }
  210.  
  211. BOOL IsValidHqueue( HQUEUE hq)
  212. {
  213.  
  214.     if (IsBadReadPtr(hq, sizeof(HQUEUE)) == TRUE)
  215.         return(FALSE);
  216.  
  217.     if (hq->dwMagic != MAGIC)
  218.         return(FALSE);
  219.  
  220.     return(TRUE);
  221. }
  222.  
  223. DWORD CreateQueue( PHQUEUE phq, int fQueueOrder, LPTSTR pszName)
  224. {
  225.     HQUEUE hq;
  226.     LPTSTR pszBase;
  227.     int    cb;
  228.     HANDLE hEvent;
  229.     HANDLE hSem;
  230.     int    iIndex = -1;
  231.     PQUEUE_DATA pqd;
  232.     int    ii;
  233.     ATOM   atom;
  234.  
  235.  
  236.     if (strncmp(pszName, "\\queues\\", 8) == 0)
  237.         pszName += 8;
  238.  
  239.     if ((cb = strlen(pszName)) == 0)
  240.         {
  241.         return(QUE_INVALID_NAME);
  242.         }
  243.  
  244.     if (strchr(pszName, '\\') != NULL)
  245.         {
  246.         return(QUE_INVALID_NAME);
  247.         }
  248.  
  249.     if ((atom = GlobalAddAtom(pszName)) == 0)
  250.         {
  251.         return(GetLastError());
  252.         }
  253.  
  254.     WaitForSingleObject(hGlobalSem, INFINITE);
  255.  
  256.     if (iQueues == QUEUE_LIMIT)
  257.         {
  258.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  259.         GlobalDeleteAtom(atom);
  260.         return( QUE_NO_MEMORY);
  261.         }
  262.  
  263.     pqd = (PQUEUE_DATA) lpCtrlBase;
  264.  
  265.     ii = 0;
  266.     while (iIndex == -1 && ii < QUEUE_LIMIT)
  267.         {
  268.         if (pqd[ii].aQueueName == 0)
  269.             iIndex = ii;
  270.         else
  271.             ii++;
  272.         }
  273.  
  274.     if (iIndex == -1)
  275.         {
  276.         GlobalDeleteAtom(atom);
  277.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  278.         return( QUE_NO_MEMORY);
  279.         }
  280.  
  281.  
  282.     pszBase = malloc(cb + 6);
  283.     strcpy( pszBase, pszName);
  284.     strcat( pszBase, "_Event");
  285.  
  286.     hEvent = CreateEvent( NULL, TRUE, FALSE, pszBase);
  287.  
  288.     if (hEvent == NULL)
  289.         {
  290.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  291.         GlobalDeleteAtom(atom);
  292.         free(pszBase);
  293.         return(GetLastError());
  294.         }
  295.  
  296.     strcpy( pszBase, pszName);
  297.     strcat( pszBase, "_Sem");
  298.  
  299.     hSem = CreateSemaphore( NULL, 1, 1, pszBase);
  300.  
  301.     if (hSem == NULL)
  302.         {
  303.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  304.         GlobalDeleteAtom(atom);
  305.         free(pszBase);
  306.         CloseHandle(hEvent);
  307.         return(GetLastError());
  308.         }
  309.  
  310.  
  311.     hq = (HQUEUE) malloc(sizeof(QUEUE));
  312.  
  313.     if (!hq)
  314.         {
  315.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  316.         return( QUE_NO_MEMORY);
  317.         }
  318.  
  319.     hq->dwMagic   = MAGIC;
  320.     hq->hEvent    = hEvent;
  321.     hq->hSem      = hSem;
  322.     hq->iIndex    = iIndex;
  323.     hq->dwProcId  = GetCurrentProcessId();
  324.  
  325.     pqd[iIndex].wType      = fQueueOrder;
  326.     pqd[iIndex].dwCreator  = hq->dwProcId;
  327.     pqd[iIndex].aQueueName = atom;
  328.     pqd[iIndex].sElements  = 0;
  329.  
  330.     *phq = hq;
  331.     ReleaseSemaphore(hGlobalSem, 1, NULL);
  332.     return(0);
  333. }
  334.  
  335. DWORD CloseQueue( HQUEUE hq)
  336. {
  337.     PQUEUE_DATA pqd;
  338.     int         iIndex;
  339.     int         ii;
  340.     DWORD       dwProcId;
  341.     HANDLE      hSem;
  342.  
  343.     if (!IsValidHqueue( hq))
  344.         return(QUE_INVALID_HANDLE);
  345.  
  346.  
  347.     WaitForSingleObject(hSem = hq->hSem, INFINITE);
  348.  
  349.     iIndex = hq->iIndex;
  350.  
  351.     pqd = (PQUEUE_DATA) lpCtrlBase;
  352.  
  353.     dwProcId = hq->dwProcId;
  354.     CloseHandle(hq->hEvent);
  355.     free(hq);
  356.  
  357.     if (pqd[iIndex].aQueueName != 0)
  358.         GlobalDeleteAtom(pqd[iIndex].aQueueName);
  359.  
  360.     if (dwProcId != pqd[iIndex].dwCreator)
  361.         {
  362.         ReleaseSemaphore(hSem, 1, NULL);
  363.         CloseHandle(hSem);
  364.         return(0);
  365.         }
  366.  
  367.     for (ii = 0; ii < pqd[iIndex].sElements ; ii++)
  368.         {
  369.         ShrFree(pqd[iIndex].elem[ii].dwShrHandle);
  370.         }
  371.  
  372.     pqd[iIndex].aQueueName = 0;
  373.     pqd[iIndex].dwCreator  = 0;
  374.     ReleaseSemaphore(hSem, 1, NULL);
  375.     CloseHandle(hSem);
  376.     return(0);
  377. }
  378.  
  379. DWORD OpenQueue(LPDWORD ppid, PHQUEUE phq, LPTSTR pszName)
  380. {
  381.     HQUEUE hq;
  382.     LPTSTR pszBase;
  383.     int    cb;
  384.     HANDLE hEvent;
  385.     HANDLE hSem;
  386.     int    iIndex = -1;
  387.     PQUEUE_DATA pqd;
  388.     int    ii;
  389.     ATOM   atom;
  390.  
  391.  
  392.     pqd = (PQUEUE_DATA) lpCtrlBase;
  393.  
  394.     if (strncmp(pszName, "\\queues\\", 8) == 0)
  395.         pszName += 8;
  396.  
  397.     if ((cb = strlen(pszName)) == 0)
  398.         return(QUE_INVALID_NAME);
  399.  
  400.     if (strchr(pszName, '\\') != NULL)
  401.         return(QUE_INVALID_NAME);
  402.  
  403.     if ((atom = GlobalAddAtom(pszName)) == 0)
  404.         return(GetLastError());
  405.  
  406.     hq = (HQUEUE) malloc(sizeof(QUEUE));
  407.  
  408.     if (!hq)
  409.         return(QUE_NO_MEMORY);
  410.  
  411.     WaitForSingleObject(hGlobalSem, INFINITE);
  412.  
  413.     ii = 0;
  414.     while (iIndex == -1 && ii < QUEUE_LIMIT)
  415.         {
  416.         if (pqd[ii].aQueueName == atom)
  417.             iIndex = ii;
  418.         else
  419.             ii++;
  420.         }
  421.  
  422.     if (iIndex == -1)
  423.         {
  424.         free(hq);
  425.         ReleaseSemaphore(hGlobalSem, 1, NULL);
  426.         return( QUE_NAME_NOT_EXIST);
  427.         }
  428.  
  429.     pszBase = malloc(cb + 6);
  430.     strcpy( pszBase, pszName);
  431.     strcat( pszBase, "_Event");
  432.  
  433.     hEvent = CreateEvent( NULL, TRUE, FALSE, pszBase);
  434.  
  435.     if (hEvent == NULL)
  436.         {
  437.         free(hq);
  438.         GlobalDeleteAtom(atom);
  439.         free(pszBase);
  440.         return(GetLastError());
  441.         }
  442.  
  443.     strcpy( pszBase, pszName);
  444.     strcat( pszBase, "_Sem");
  445.  
  446.     hSem = CreateSemaphore( NULL, 1, 1, pszBase);
  447.  
  448.     if (hSem == NULL)
  449.         {
  450.         free(hq);
  451.         GlobalDeleteAtom(atom);
  452.         free(pszBase);
  453.         CloseHandle(hEvent);
  454.         return(GetLastError());
  455.         }
  456.  
  457.     hq->dwMagic   = MAGIC;
  458.     hq->hEvent    = hEvent;
  459.     hq->hSem      = hSem;
  460.     hq->iIndex    = iIndex;
  461.     hq->dwProcId  = GetCurrentProcessId();
  462.  
  463.     *ppid = pqd[iIndex].dwCreator;
  464.     *phq = hq;
  465.     ReleaseSemaphore(hGlobalSem, 1, NULL);
  466.     return(0);
  467. }
  468.  
  469. void push_down( int iIndex, int jj)
  470. {
  471.     PQUEUE_DATA pqd;
  472.     int ii;
  473.  
  474.     pqd = (PQUEUE_DATA) lpCtrlBase;
  475.  
  476.     for (ii = pqd[iIndex].sElements; ii > jj; ii--)
  477.         pqd[iIndex].elem[ii] = pqd[iIndex].elem[ii -1];
  478. }
  479.  
  480. void push_up( int iIndex, int jj)
  481. {
  482.     PQUEUE_DATA pqd;
  483.     int ii;
  484.  
  485.     pqd = (PQUEUE_DATA) lpCtrlBase;
  486.  
  487.     for (ii = jj; ii < pqd[iIndex].sElements; ii++)
  488.         pqd[iIndex].elem[ii] = pqd[iIndex].elem[ii +1];
  489. }
  490.  
  491. DWORD WriteQueue(HQUEUE hq, DWORD dwEventCode, DWORD dwShrHandle, DWORD dwPriority)
  492. {
  493.     int iIndex;
  494.     PQUEUE_DATA pqd;
  495.     int ii;
  496.  
  497.     if (!IsValidHqueue( hq))
  498.         return(QUE_INVALID_HANDLE);
  499.  
  500.     WaitForSingleObject( hq->hSem, INFINITE);
  501.  
  502.     iIndex = hq->iIndex;
  503.  
  504.     pqd = (PQUEUE_DATA) lpCtrlBase;
  505.  
  506.     if (pqd[iIndex].sElements == QUEUE_LIMIT)
  507.         {
  508.         ReleaseSemaphore(hq->hSem, 1, NULL);
  509.         return(QUE_NO_MEMORY);
  510.         }
  511.  
  512.     if (pqd[iIndex].sElements == 0)
  513.         ii = 0;
  514.     else
  515.         {
  516.         if (pqd[iIndex].wType == QUE_FIFO)
  517.             ii = pqd[iIndex].sElements;
  518.         if (pqd[iIndex].wType == QUE_LIFO)
  519.             {
  520.             push_down(iIndex, 0);
  521.             ii = 0;
  522.             }
  523.         if (pqd[iIndex].wType == QUE_PRIORITY)
  524.             {
  525.             ii = 0;
  526.             while (ii < pqd[iIndex].sElements &&
  527.                         dwPriority < pqd[iIndex].elem[ii].dwPriority)
  528.                 ii++;
  529.             if (ii != pqd[iIndex].sElements)
  530.                 push_down( iIndex, ii);
  531.             }
  532.         }
  533.  
  534.     pqd[iIndex].elem[ii].dwWriterId  = hq->dwProcId;
  535.     pqd[iIndex].elem[ii].dwShrHandle = dwShrHandle;
  536.     pqd[iIndex].elem[ii].dwEventCode = dwEventCode;
  537.     pqd[iIndex].elem[ii].dwPriority  = dwPriority;
  538.     pqd[iIndex].sElements++;
  539.  
  540.     SetEvent(hq->hEvent);
  541.     ReleaseSemaphore(hq->hSem, 1, NULL);
  542.     return(0);
  543.  
  544. }
  545.  
  546.                                   
  547. DWORD ReadQueue(HQUEUE hq, PQ_ELEMENT pqe, int iElement, BOOL fWait)
  548. {
  549.  
  550.     int iIndex;
  551.     PQUEUE_DATA pqd;
  552.  
  553.  
  554.     if (!IsValidHqueue( hq))
  555.         return(QUE_INVALID_HANDLE);
  556.  
  557.     WaitForSingleObject(hq->hSem, INFINITE);
  558.  
  559.     iIndex = hq->iIndex;
  560.  
  561.     pqd = (PQUEUE_DATA) lpCtrlBase;
  562.  
  563.     if (hq->dwProcId != pqd[iIndex].dwCreator)
  564.         {
  565.         ReleaseSemaphore(hq->hSem, 1, NULL);
  566.         return(QUE_INVALID_HANDLE);
  567.         }
  568.  
  569.     if (iElement < 0)
  570.         iElement = 0;
  571.  
  572.     if (iElement >= pqd[iIndex].sElements && iElement != 0)
  573.         {
  574.         ReleaseSemaphore(hq->hSem, 1, NULL);
  575.         return(QUE_ELEMENT_NOT_EXIST);
  576.         }
  577.  
  578.     if (pqd[iIndex].sElements == 0)
  579.         if (fWait)
  580.             {
  581.             while (pqd[iIndex].sElements == 0)
  582.                 {
  583.                 ReleaseSemaphore(hq->hSem, 1, NULL);
  584.                 WaitForSingleObject(hq->hEvent, INFINITE);
  585.                 WaitForSingleObject(hq->hSem, INFINITE);
  586.                 }
  587.             }
  588.         else
  589.             return(QUE_EMPTY);
  590.  
  591.     *pqe = pqd[iIndex].elem[iElement];
  592.     push_up(iIndex, iElement);
  593.     pqd[iIndex].sElements --;
  594.  
  595.     if (pqd[iIndex].sElements == 0)
  596.         ResetEvent(hq->hEvent);
  597.  
  598.     ReleaseSemaphore(hq->hSem, 1, NULL);
  599.     return(0);
  600.  
  601. }
  602.  
  603. HANDLE GetQueueEventHandle( HQUEUE hq)
  604. {
  605.     if (hq->dwMagic != MAGIC)
  606.         return(0);
  607.  
  608.     return( hq->hEvent);
  609. }
  610.  
  611.  
  612. DWORD PeekQueue(HQUEUE hq, PQ_ELEMENT pqe, int *piElement, BOOL fWait)
  613. {
  614.  
  615.     int iIndex;
  616.     PQUEUE_DATA pqd;
  617.  
  618.     if (!IsValidHqueue( hq))
  619.         return(QUE_INVALID_HANDLE);
  620.  
  621.     WaitForSingleObject(hq->hSem, INFINITE);
  622.  
  623.     iIndex = hq->iIndex;
  624.  
  625.     pqd = (PQUEUE_DATA) lpCtrlBase;
  626.  
  627.     if (hq->dwProcId != pqd[iIndex].dwCreator)
  628.         {
  629.         ReleaseSemaphore(hq->hSem, 1, NULL);
  630.         return(QUE_INVALID_HANDLE);
  631.         }
  632.  
  633.     if (*piElement < 0)
  634.         *piElement = 0;
  635.     else
  636.         (*piElement)++;
  637.  
  638.     if (*piElement >= pqd[iIndex].sElements && *piElement != 0)
  639.         {
  640.         ReleaseSemaphore(hq->hSem, 1, NULL);
  641.         return(QUE_ELEMENT_NOT_EXIST);
  642.         }
  643.  
  644.     if (pqd[iIndex].sElements == 0)
  645.         if (fWait)
  646.             {
  647.             while (pqd[iIndex].sElements == 0)
  648.                 {
  649.                 ReleaseSemaphore(hq->hSem, 1, NULL);
  650.                 WaitForSingleObject(hq->hEvent, INFINITE);
  651.                 WaitForSingleObject(hq->hSem, INFINITE);
  652.                 }
  653.             }
  654.         else
  655.             return(QUE_EMPTY);
  656.  
  657.     *pqe = pqd[iIndex].elem[*piElement];
  658.  
  659.     ReleaseSemaphore(hq->hSem, 1, NULL);
  660.     return(0);
  661.  
  662.  
  663. }
  664.  
  665.